package cn.edu.zufe.mjt.bfs;

import java.util.*;

/**
 * 广度优先搜索——连通块问题
 * 题目描述:
 * 给定一个无向图，该图通过邻接表的方式存储。请你使用广度优先搜索(BFS)算法计算该图的连通块数量。
 * 在无向图中，一个连通块是指图中所有节点之间有路径相连的最大子图。你需要输出图中连通块的数量。
 * 输入
 * 第一行包含两个整数n和 m(2 <n< 104,1<m < 105)，表示图中有几 个节点和 m 条边
 * 接下来的 m 行，每行包含两个整数 u和 v (1 < u,v< n)，表示存在一条从节点u 到节点 v 的无向边。
 * 输出
 * 输出一个整数，表示图中连通块的数量。
 */
public class Unicomlock {

    private static int[] visited ;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        visited = new int[n];
        List<List<Integer>> edges = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            edges.add(new ArrayList<>());
        }
        for (int i = 0; i < m; i++) {
            int u = sc.nextInt();
            int v = sc.nextInt();
            edges.get(u - 1).add(v - 1);
            edges.get(v - 1).add(u - 1);
        }
        int count = countUnicomlock(n, edges);
        System.out.println(count);

    }

    public static int countUnicomlock(int n, List<List<Integer>> edges) {
        int count = 0;
        for (int i = 0; i < n; i++) {
            if (visited[i] == 0) {
                bfs(i, visited, edges);
                count++;
            }
        }
        return count;
    }

    private static void bfs(int i, int[] visited, List<List<Integer>> edges) {
        Queue<Integer> queue = new LinkedList<>();
        queue.add(i);
        visited[i] = 1;
        while (!queue.isEmpty()) {
            int node = queue.poll();
            for (int neighbor : edges.get(node)) {
                if (visited[neighbor] == 0) {
                    queue.add(neighbor);
                    visited[neighbor] = 1;
                }
            }
        }
    }
}
